<template>
  <div class="chat-container">
    <!-- 左侧会话列表 -->
    <el-card class="conversation-list">
      <el-button type="primary" @click="openBlock" class="mt-2" block>
        新建对话
      </el-button>
      <el-scrollbar height="800">
        <el-menu :default-active="activeConversationId" @select="loadMessages">
          <el-menu-item
            v-for="conv in conversations"
            :key="conv?.id ?? 'unknown'"
            :index="conv?.id ? conv.id.toString() : ''"
          >
            {{ conv?.title}}
          </el-menu-item>
        </el-menu>
      </el-scrollbar>
    </el-card>

    <!-- 右侧聊天窗口 -->
    <div class="chat-box">
      <el-card class="messages" ref="messageBox">
        <div
          v-for="(msg, idx) in messages"
          :key="idx"
          class="message-item"
          :class="msg.type"
        >
          <div class="avatar">
            <el-avatar
              v-if="msg.type === 'user'"
              icon="User"
              style="background-color: #409EFF"
            />
            <el-avatar
              v-else
              icon="Cpu"
              style="background-color: #67C23A"
            />
          </div>
          <div class="content">
            <div class="msg-card">{{ msg.content }}</div>
          </div>
        </div>
      </el-card>

      <div class="input-area">
        <el-input
          v-model="inputMessage"
          type="textarea"
          placeholder="请输入你的问题..."
          :rows="2"
          @keyup.enter.native="sendStreamMessage"
        />
        <el-button type="primary" @click="sendStreamMessage">发送</el-button>
      </div>
    </div>

    <!-- 新建会话弹窗 -->
    <el-dialog v-model="dialogVisible" title="新建对话" width="500px">
      <el-form :model="form" label-width="100px">
        <el-form-item label="标题" required>
          <el-input v-model="form.title" placeholder="请输入对话标题" />
        </el-form-item>
        <el-form-item label="角色" required>
          <el-select v-model="form.roleId" placeholder="请选择角色" @change="setRole">
            <el-option
              v-for="role in roleList"
              :key="role.id"
              :label="role.name"
              :value="role.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="模型" required>
          <el-select v-model="form.model" placeholder="请选择模型" @change="setModel">
            <el-option
              v-for="model in modelList"
              :key="model.id"
              :label="model.name"
              :value="model.id"
            />
          </el-select>
        </el-form-item>
        <el-form-item label="最大Token">
          <el-input-number v-model="form.maxTokens" :min="512" :max="4096" />
        </el-form-item>
        <el-form-item label="上下文消息数">
          <el-input-number v-model="form.maxContexts" :min="1" :max="20" />
        </el-form-item>
        <el-form-item label="温度">
          <el-slider v-model="form.temperature" :min="0" :max="1" :step="0.1" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="createConversation">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, nextTick } from "vue";
import { ElMessage } from "element-plus";
import axios from "axios";
import { ModelApi, ModelVO } from '@/api/ai/model/model'
import { ChatRoleApi, ChatRoleVO } from '@/api/ai/model/chatRole'

const modelList = ref([] as ModelVO[])
const roleList = ref([] as ChatRoleVO[])
const conversations = ref([])
const messages = ref([])
const activeConversationId = ref(null)
const inputMessage = ref("")
const messageBox = ref(null)

// 弹窗控制
const dialogVisible = ref(false)
const form = ref({
  userId: 1,
  title: "",
  model:"",
  modelId: 1,
  pinned: false,
  roleId: null,
  roleName: "",
  maxTokens: 2048,
  maxContexts: 10,
  temperature: 0.3,
})

const openBlock = async() => {
  dialogVisible.value = true
  const keyData = await ModelApi.getModelList({})
  modelList.value = keyData.data

  const roleData = await ChatRoleApi.getChatRoleList({})
  roleList.value = roleData.data
}

const setModel = (val:any) => {
  const model = modelList.value.find(m => m.id === val)
  if(model) {
    form.value.model = model.name
    form.value.modelId = model.id
  }
}

const setRole = (val:any) => {
  const role = roleList.value.find(m => m.id === val)
  if(role) {
    form.value.roleName = role.category
    form.value.roleId = role.id
    form.value.modelId = role.modelId
  }
}

const scrollToBottom = () => {
  nextTick(() => {
    if (messageBox.value) {
      messageBox.value.scrollTop = messageBox.value.scrollHeight
    }
  })
}

// 获取会话列表
const loadConversations = async () => {
  try {
    const res = await axios.get("http://192.168.2.13:8081/ai/chat/conversation/list", {
      params: { userId: 1 },
    })
    conversations.value = res.data
    if (conversations.value.length > 0) {
      activeConversationId.value = conversations.value[0].id
      await loadMessages(activeConversationId.value)
    }
  } catch {
    ElMessage.error("加载会话失败")
  }
}

// 获取消息
const loadMessages = async (conversationId:any) => {
  activeConversationId.value = conversationId
  try {
    const res = await axios.get("http://192.168.2.13:8081/ai/chat/conversation/history", {
      params: { conversationId },
    })
    messages.value = res.data
    scrollToBottom()
  } catch {
    ElMessage.error("加载消息失败")
  }
}

// 新建会话
const createConversation = async () => {
  if (!form.value.title) {
    return ElMessage.warning("请输入标题")
  }
  if (!form.value.roleId) {
    return ElMessage.warning("请选择角色")
  }
  if (!form.value.model) {
    return ElMessage.warning("请选择模型")
  }

  try {
    const res = await axios.post(
      "http://192.168.2.13:8081/ai/chat/conversation/create",
      form.value
    )
    conversations.value.unshift(res.data)
    activeConversationId.value = res.data.id
    messages.value = []
    dialogVisible.value = false
    ElMessage.success("会话创建成功")
  } catch {
    ElMessage.error("新建会话失败")
  }
}

// 发送消息
const sendMessage = async () => {
  if (!inputMessage.value.trim()) {
    return ElMessage.warning("请输入内容")
  }

  const userMsg = { type: "user", content: inputMessage.value }
  messages.value.push(userMsg)
  scrollToBottom()

  const tempInput = inputMessage.value
  inputMessage.value = ""

  try {
    const res = await axios.post("http://192.168.2.13:8081/ai/chat/conversation/send", {
      conversationId: activeConversationId.value,
      userId: 1,
      content: tempInput,
      useContext: true,
    })
    const aiMsg = { type: "assistant", content: res.data.receive.content }
    messages.value.push(aiMsg)
    scrollToBottom()
  } catch {
    ElMessage.error("发送失败")
  }
}
// 发送消息（流式版）
const sendStreamMessage = async () => {
  if (!inputMessage.value.trim()) {
    return ElMessage.warning("请输入内容");
  }
  
  // 先插入用户消息
  const userMsg = {
    role: "user",
    content: inputMessage.value,
  };
  messages.value.push(userMsg);
  scrollToBottom();

  const tempInput = inputMessage.value;
  inputMessage.value = "";
  // 然后调用流式接口
  const response = await fetch("http://192.168.2.13:8081/ai/chat/conversation/sendStream", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      conversationId: activeConversationId.value,
      userId: 1,
      content: tempInput,
      useContext:true,
    }),
  });
  debugger
  const reader = response.body.getReader();
  let decoder = new TextDecoder("utf-8");
  let aiReply = { role: "assistant", content: "" };
  messages.value.push(aiReply);
  scrollToBottom();

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    // console.log("Received chunk", { done, value });
    // aiReply.content += decoder.decode(value, { stream: true });
     // 解码并拼接数据
    const text = decoder.decode(value, { stream: true });
    const chunks = text.split("\n");  // 每一行是一个数据块
    debugger
    for (let chunk of chunks) {
      if (chunk.startsWith("data:")) {
        // 解析出 `data: {}` 中的内容
        const data = chunk.slice(5).trim();
        if (data && data !== "[DONE]") {
          try {
            const messageData = JSON.parse(data);
            
            // 根据消息类型，决定是用户消息还是 AI 回复
            if (messageData.receive && messageData.receive.content) {
                            // 每次接收到新的内容时拼接并更新 aiReply
              aiReply.content += messageData.receive.content;
              
              // 强制 Vue 更新
              const updatedReply = { ...aiReply }; // 通过解构创建新对象，确保 Vue 侦测到更新
              messages.value = [...messages.value]; // 强制更新消息数组
              scrollToBottom(); // 滚动到最新消息
            }
          } catch (error) {
            console.error("解析流数据时出错：", error);
          }
        }
      }
    }
  }
};

onMounted(() => {
  loadConversations()
})
</script>

<style scoped>
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  background-color: #f0f2f5;
}
.chat-container {
  display: flex;
  height: 100vh;
  box-sizing: border-box;
  padding: 20px;
}

.conversation-list {
  width: 250px;
  margin-right: 16px;
  display: flex;
  flex-direction: column;
}

.chat-box {
  flex: 1;
  display: flex;
  flex-direction: column;
}

.messages {
  flex: 1;
  overflow-y: auto;
  margin-bottom: 16px;
  padding: 12px;
}

.message-item {
  display: flex;
  align-items: flex-start;
  margin-bottom: 12px;
}

/* 用户消息：整体靠右，头像在右，文字在左 */
.message-item.user {
  flex-direction: row-reverse; /* 反转顺序：头像在右 */
  /* justify-content: flex-end; */
}
.message-item.user .msg-card {
  background-color: #409eff;
  color: #fff;
  border-radius: 12px 12px 0 12px;
  text-align: right;
}

/* 助手消息：整体靠左，头像在左，文字在右 */
.message-item.assistant {
  flex-direction: row; /* 正常顺序：头像在左 */
  justify-content: flex-start;
}
.message-item.assistant .msg-card {
  background-color: #f5f5f5;
  color: #333;
  border-radius: 12px 12px 12px 0;
  text-align: left;
}

.avatar {
  flex-shrink: 0;
  margin: 0 8px;
}

.content {
  max-width: 60%;
}

.msg-card {
  padding: 10px 14px;
  word-wrap: break-word;
  white-space: pre-wrap;
  line-height: 1.6;
  font-size: 14px;
}

.input-area {
  display: flex;
  gap: 12px;
  align-items: center;
}
</style>